using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using NPOI.HSSF.Record.Crypto;
using NPOI.HSSF.UserModel;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;

namespace timetable
{
    partial class CourseSchedule
    {
        // 可控参数
        public int minSplitGourpNum = 50; // 分组拆分的临界人数，若大于，则拆成两个分组
        public readonly int CourseNumADay = 8;
        public int MaxPeople = 60; // 一个班级的最大人数

        public GroupList rawList = new GroupList();
        // 存储合并之后的分组数据
        public List<GroupList> resultGroupLists = new List<GroupList>();
        private List<GroupList> bufferGroupLists = new List<GroupList>();
        // 原始的分组数据
        private GroupList rawResultList = new GroupList();
        private GroupList rawBufferList = new GroupList();

        // 重新编号之后的课程编号
        public ClassifiedCourses classifiedCourses = new ClassifiedCourses();

        // 能量表列表，存储每次变换之后的能量表
        public EnergyTable rawEnergyTable;
        public EnergyTable BetterEnergyTable;

        // 存储分班之后的班级课程情况
        public List<GroupListClass> GroupListClasses = new List<GroupListClass>();
        // 存储每个教学班的人数
        public Dictionary<string, int> studentAmountEachClass = new Dictionary<string, int>();

        private static readonly string[] Coursename =
        {
            "语文", "数学", "英语", "物理", "化学", "生物", "政治", "历史", "地理", "通技"
        };

        // 特定位置的规则表
        public List<List<string>> ExchangeRuleList { set; get; }


        public CourseSchedule(string filePath)
        {
            ExchangeRuleList = new List<List<string>>();
            GetRuleConfig(filePath);

        }

        public void ClassifyAlgorithm()
        {
            BetterEnergyTable = new EnergyTable(resultGroupLists);
            BetterEnergyTable.GetCourse(); // 遍历每个分组的每节课程，并将其加入能量表中
            BetterEnergyTable.CalculateEnergy(); // 存储能量值最高的位置的信息

            ExchangeForGroupClass();

            GenNeighbourState();
            BetterEnergyTable = new EnergyTable(BetterEnergyTable.CompareList);
            BetterEnergyTable.GetCourse();
            BetterEnergyTable.CalculateEnergy();
            ExchangeForGroupClass();
            // 将分班过后的课程班级数据进行收集整理
            GetClassAndCourses();
            // 给每个大类分教室
            ClassifyClassromm();

        }

        private void GetRuleConfig(string filePath)
        {
            // 读取课程配置文件
            // 设置4个等级
            // 1 语数外
            // 2 政史地
            // 3 理化生通技
            // 4 理化生政史地通技
            // 5 全部
            string line;
            string[] stringArray;
            char[] charArray = { '\t' };

            FileStream aFile = new FileStream(filePath, FileMode.Open);
            StreamReader sr = new StreamReader(aFile);

            line = sr.ReadLine();
            while (line != null)
            {
                stringArray = line.Split(charArray);
                List<string> dataRow = new List<string>();

                for (int x = 0; x <= stringArray.GetUpperBound(0); x++)
                {
                    string course ="";
                    course = stringArray[x];
                    dataRow.Add(course);
                }

                ExchangeRuleList.Add(dataRow);

                line = sr.ReadLine();
            }

            sr.Close();
        }
        // 生成学军中学语数外这样的课程的grouplists
        public EnergyTable GenGroupLists()
        {
            resultGroupLists = new List<GroupList>();
            // 直接生成12个班级
            for (int i = 0; i < 12; i++)
            {
                GroupList groupList = new GroupList(true);
                Group group = new Group();

                // 手动给分配课程班
                for (int j = 0; j < 5; j++)
                {
                    for (int k = 0; k < CourseNumADay; k++)
                    {
                        if (group.Curriculum.table[j][k].CourseName != "!")
                        {
                            group.Curriculum.table[j][k].Class = group.Curriculum.table[j][k].CourseName + "A0" + i;
                        }

                    }
                }

                groupList.Add(group);
                resultGroupLists.Add(groupList);
            }

            //直接开始使用能量最小化
            ClassifyAlgorithm();

            return BetterEnergyTable;

        }

        // 生成学军中学语数外这样的课程的grouplists
        public void GenGroupListsByExcelClassifiedCourse(string filePath)
        {
            List<Student> Students = new List<Student>();
            try
            {
                using (FileStream fs = new FileStream(filePath, FileMode.Open))
                {
                    IWorkbook book = new HSSFWorkbook(fs);
                    resultGroupLists = new List<GroupList>();

                    for (int m = 0; m < book.NumberOfSheets; m++)
                    {
                        ISheet sheet = book.GetSheetAt(m);
                        int groupListSubscript = m;
                        GroupList groupList = new GroupList(true);

                        int rFirst = sheet.FirstRowNum;
                        int rLast = sheet.LastRowNum;

                        for (int i = rFirst + 1; i < rLast + 1; i++)
                        {
                            IRow ir = sheet.GetRow(i);
                            string[] groupName = ir.GetCell(1).ToString().Split('_');
                            Dictionary<string, string> details = new Dictionary<string, string>();

                            // 添加该分组的details数据
                            foreach (string s in Coursename)
                            {
                                if (s == "体育" || s == "音乐" || s == "美术")
                                {
                                    continue;
                                }
                                if (s == "语文" || s == "数学" || s == "英语")
                                {
                                    details.Add(s, "A");
                                    continue;
                                }
                                if (groupName.Contains(s))
                                {
                                    details.Add(s, "选");
                                }
                                else
                                {
                                    details.Add(s, "学");
                                }
                            }

                            Group group = new Group();
                            group.Curriculum = new Curriculum();
                            group.Details = details;
                            group.count = int.Parse(ir.GetCell(2).ToString());
                            groupList.Add(group);
                        }


                        // 获得该班每个分组的共同课程和特别课程
                        Dictionary<string, string> commomDictionary =
                            new Dictionary<string, string>(groupList.List[0].Details);
                        foreach (Group @group in groupList.List)
                        {
                            commomDictionary = group.Details.Intersect(commomDictionary)
                                .ToDictionary(e => e.Key, e => e.Value);
                        }

                        foreach (Group @group in groupList.List)
                        {
                            group.Common = new Dictionary<string, string>(commomDictionary);
                            group.Special = group.Details.Except(group.Common).ToDictionary(e => e.Key, e => e.Value);

                            // 获得每个分组的courseSet
                            foreach (KeyValuePair<string, string> pair in group.Common)
                            {
                                group.Curriculum.CourseSet.Add(pair.Key + groupListSubscript + pair.Value + 0);
                            }
                            foreach (KeyValuePair<string, string> pair in group.Special)
                            {
                                group.Curriculum.CourseSet.Add(pair.Key + groupListSubscript + pair.Value + 1);
                            }
                        }

                        // 获得groupList的courseSet
                        foreach (Group @group in groupList.List)
                        {
                            groupList.CourseSet.UnionWith(group.Curriculum.CourseSet);
                        }
                        sheet = null;

                        // 修改group中课表的courseName
                        foreach (Group @group in groupList.List)
                        {
                            foreach (List<CourseCell> cells in group.Curriculum.table)
                            {
                                foreach (CourseCell cell in cells)
                                {
                                    foreach (string s in group.Curriculum.CourseSet)
                                    {
                                        if (s.Substring(0, 2) == cell.CourseName)
                                        {
                                            cell.CourseName = s;
                                            cell.isSpecialCourse = 0;
                                            if (s.Substring(s.Length - 1, 1) == "1")
                                            {
                                                cell.isSpecialCourse = 1;
                                            }
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        // 将groupList加入resultGrouLists中
                        resultGroupLists.Add(groupList);
                    }


                    book = null;
                }
            }
            catch (Exception)
            {

                Console.WriteLine("错误");
                Console.ReadKey();
            }

            GenCourseResultNum();

        //???    UpdateCourseTableForDiffLevel();

            // 通过增加额外教室来均衡老师的工作量的问题
            //AddNewClassroomForTeacher("物理学11","物理学12");
            //UseNewClassroomToDecreaseEnergyValue();
            //直接开始使用能量最小化
            //BetterEnergyTable = new EnergyTable(resultGroupLists);
            //BetterEnergyTable.GetCourse();
            //BetterEnergyTable.CalculateEnergy(0.3, 0.7);

            //// 每调整一节课程，需要遍历所有的分组，相同的课程全部都要进行调整
            //ExchangeForClassifiedGroupClass();


        }

        public void Classify()
        {

            // 将初始分组分到结果区和缓冲区中
            var rawGroupQuery =
                from rawGroup in rawList.List
                where rawGroup.count > 30
                select rawGroup;


            /* 
                     /^\    /^\
                    {  O}  {  O}
                     \ /    \ /
                     //     //       _------_
                    //     //     ./~        ~-_
                   / ~----~/     /              \
                 /         :   ./       _---_    ~-
                |  \________) :       /~     ~\   |
                |        /    |      |  :~~\  |   |
                |       |     |      |  \___-~    |
                |        \ __/`\______\.        ./
                 \                     ~-______-~\.
                 .|                                ~-_
                /_____________________________________~~____
             * 在将原始组的数据移到新的变量中的时候
             * 一定要注意变量引用的问题
             * 如果该组没有进行拆分操作则不影响
             * 如果进行拆分操作，一定要注意拆分过后的两个组都要进行深复制
             * 否则很容易出现引用数据变化
             */
            foreach (Group @group in rawGroupQuery)
            {
                // 该组人数比较多的时候进行自动拆分
                if (group.count > minSplitGourpNum)
                {
                    int groupSumCount = group.count;
                    while (groupSumCount > 50)
                    {
                        rawResultList.Add(
                            new Group
                            {
                                count = 50,
                                Common = new Dictionary<string, string>(group.Details),
                                Details = new Dictionary<string, string>(group.Details),
                                Special = new Dictionary<string, string>(group.Special),
                                Curriculum = new Curriculum()
                            });
                        // 学军中学需要分组的课程模板读取指定文件路径
                        rawResultList.List.Last().Curriculum = new Curriculum();

                        groupSumCount -= rawResultList.List.Last().count;

                        //将人数达到50人的直接放到结果组中（因此并且也不会参与合并分组）
                        GroupList one = new GroupList();
                        one.isResult = true;
                        one.CourseSet = new HashSet<string>();

                        one.Add(rawResultList.List.Last());
                        resultGroupLists.Add(one);

                        // 获取one在resultGroupLists的下标
                        // 对CourseSet的班级编号进行重写
                        int goodGroupListSubscript = resultGroupLists.Count - 1;
                        string[] CourseSetArray = new string[one.CourseSet.Count];
                        one.CourseSet.CopyTo(CourseSetArray);

                        for (int j = 0; j < one.CourseSet.Count; j++)
                        {
                            CourseSetArray[j] = CourseSetArray[j].Replace("3", goodGroupListSubscript.ToString());
                        }

                        one.CourseSet.Clear();
                        one.CourseSet = new HashSet<string>(CourseSetArray);

                        // 更新每个分组的courseSet
                        foreach (Group @g in one.List)
                        {
                            CourseSetArray = new string[10];
                            @g.Curriculum.CourseSet.CopyTo(CourseSetArray);
                            for (int j = 0; j < 10; j++)
                            {
                                if (CourseSetArray[j] != null)
                                    CourseSetArray[j] = CourseSetArray[j].Replace("3", goodGroupListSubscript.ToString());
                            }
                            @g.Curriculum.CourseSet.Clear();
                            @g.Curriculum.CourseSet = new HashSet<string>(CourseSetArray);
                        }
                    }

                    rawResultList.Add(
                        new Group
                        {
                            count = groupSumCount,
                            Common = new Dictionary<string, string>(group.Common),
                            Details = new Dictionary<string, string>(group.Details),
                            Special = new Dictionary<string, string>(group.Special),
                            Curriculum = new Curriculum()
                        });


                    // 学军中学需要分组的课程模板读取指定文件路径
                    rawResultList.List.Last().Curriculum = new Curriculum();
                }
                else
                {
                    rawResultList.Add(group);
                }

            }

            var rawGroupQuery1 =
                from rawGroup in rawList.List
                where rawGroup.count < 30
                select rawGroup;

            foreach (Group @group in rawGroupQuery1)
            {
                rawBufferList.Add(group);
            }

            //比较缓冲区课程和结果区课程不同的具体课程数目，确定合并的优先级
            // 学军中学的分班之后的数据还是有些特殊，因此
            MergeGroup(rawResultList, rawBufferList, false);

            Console.WriteLine("第二次！！！！！！！");

            MergeGroup(bufferGroupLists[0], bufferGroupLists[0], true);
            Console.WriteLine("三个组合并");
            MergeThreeGroup(bufferGroupLists[1]);
            RetailProcess();
            GenCourseResultNum();
    //???        UpdateCourseTableForDiffLevel();

            foreach (Group @group in resultGroupLists[5].List)
            {
                foreach (string s in group.Curriculum.CourseSet)
                {
                    Console.Write(s + " ");
                }
                Console.WriteLine();
                foreach (List<CourseCell> cells in group.Curriculum.table)
                {
                    foreach (CourseCell cell in cells)
                    {
                        Console.Write(cell.Class + "  ");
                    }
                    Console.WriteLine();
                }
                Console.WriteLine();
            }

            ClassifyAlgorithm();



        }

        private void MergeGroup(GroupList resultList, GroupList bufferList, bool isBuffer)
        {

            StreamWriter sw = new StreamWriter("log.txt", true);


            List<Dictionary<string, int>> resultCompare = new List<Dictionary<string, int>>();
            List<DiffGroup> diffGroups = new List<DiffGroup>();

            Group extraGroup = null;

            int resultSubscript = 0;
            foreach (Group rGroup in resultList.List)
            {
                int bufferSubscript = 0;

                foreach (Group bGroup in bufferList.List)
                {
                    var diff = rGroup.Details.Except(bGroup.Details);
                    DiffGroup diffGroup = new DiffGroup();
                    diffGroup.bufferSubscript = bufferSubscript;
                    diffGroup.resultSubscript = resultSubscript;
                    foreach (KeyValuePair<string, string> keyValuePair in diff)
                    {
                        diffGroup.Special.Add(keyValuePair.Key, keyValuePair.Value);
                    }
                    diffGroups.Add(diffGroup);
                    bufferSubscript++;
                }

                resultSubscript++;
            }

            var SortDiffGroup =
                from diffGroup in diffGroups
                orderby diffGroup.Count
                select diffGroup;


            foreach (var diffResult in SortDiffGroup)
            {
                if (
                    (diffResult.Count == 0 ||
                     diffResult.Count > 3 ||
                     bufferList.List[diffResult.bufferSubscript].count +
                     resultList.List[diffResult.resultSubscript].count < 30))
                    continue;

                Dictionary<string, int> fuckDictionary = new Dictionary<string, int>
                {
                    {"差别", diffResult.Count},
                    {
                        "总数", bufferList.List[diffResult.bufferSubscript].count +
                              resultList.List[diffResult.resultSubscript].count
                    },
                    {"结果组人数", resultList.List[diffResult.resultSubscript].count},
                    {"缓冲组人数", bufferList.List[diffResult.bufferSubscript].count},
                    {"结果组下标", diffResult.resultSubscript},
                    {"缓冲组下标", diffResult.bufferSubscript}
                };
                resultCompare.Add(fuckDictionary);
            }

            var mergeQuery =
                from compare in resultCompare
                orderby compare["差别"] ascending, compare["总数"] descending
                select compare;

            // 输出第一次预合并结果
            foreach (Dictionary<string, int> dictionary in mergeQuery)
            {
                foreach (KeyValuePair<string, int> keyValuePair in dictionary)
                {
                    sw.Write(keyValuePair.Value + "\t");
                    Console.Write(keyValuePair.Value + "\t");
                }
                sw.WriteLine();
                Console.WriteLine();
            }

            // 合并分组

            HashSet<int> classifiedBSubscript = new HashSet<int>();
            HashSet<int> classifiedRSubscript = new HashSet<int>();
            foreach (Dictionary<string, int> dictionary in mergeQuery)
            {

                // 记录该次分组调取的下标
                int bSubscript = dictionary["缓冲组下标"];
                int rSubscript = dictionary["结果组下标"];

                // 如果该分组在之前已经被调用过了，则不再让其参与分组合并工作
                if (!classifiedBSubscript.Contains(bSubscript) && !classifiedRSubscript.Contains(rSubscript))
                {
                    if (dictionary["总数"] < 51 && dictionary["总数"] > 30)
                    {

                        GroupList goodGroupList = new GroupList(true); // 存储这一次合并分组的结果

                        Group addedRGroup = resultList.List[rSubscript];
                        Group addedBGroup = bufferList.List[bSubscript];


                        addedBGroup.Special =
                            (addedBGroup.Details.Except(
                                addedRGroup.Details)).ToDictionary(e => e.Key, e => e.Value);
                        addedBGroup.Common =
                            (addedRGroup.Details.Intersect(
                                addedBGroup.Details)).ToDictionary(e => e.Key, e => e.Value);

                        addedRGroup.Special =
                            (addedRGroup.Details.Except(
                                addedBGroup.Details)).ToDictionary(e => e.Key, e => e.Value);

                        addedRGroup.Common = addedBGroup.Common;

                        classifiedBSubscript.Add(bSubscript);
                        classifiedRSubscript.Add(rSubscript);

                        if (isBuffer)
                        {
                            classifiedBSubscript.UnionWith(classifiedRSubscript);
                            classifiedRSubscript.UnionWith(classifiedBSubscript);
                        }
                        goodGroupList.Add(addedRGroup);
                        goodGroupList.Add(addedBGroup);

                        resultGroupLists.Add(goodGroupList); // 将该次分组结果存入全局变量中

                        // 获取goodGroupList在resultGroupLists的下标
                        // 对CourseSet的班级编号进行重写
                        int goodGroupListSubscript = resultGroupLists.Count - 1;
                        string[] CourseSetArray = new string[goodGroupList.CourseSet.Count];
                        goodGroupList.CourseSet.CopyTo(CourseSetArray);

                        for (int j = 0; j < goodGroupList.CourseSet.Count; j++)
                        {
                            CourseSetArray[j] = CourseSetArray[j].Replace("3", goodGroupListSubscript.ToString());
                        }

                        goodGroupList.CourseSet.Clear();
                        goodGroupList.CourseSet = new HashSet<string>(CourseSetArray);

                        // 更新每个分组的courseSet
                        foreach (Group @group in goodGroupList.List)
                        {
                            CourseSetArray = new string[10];
                            group.Curriculum.CourseSet.CopyTo(CourseSetArray);
                            for (int j = 0; j < 10; j++)
                            {
                                if (CourseSetArray[j] != null)
                                    CourseSetArray[j] = CourseSetArray[j].Replace("3", goodGroupListSubscript.ToString());
                            }
                            group.Curriculum.CourseSet.Clear();
                            group.Curriculum.CourseSet = new HashSet<string>(CourseSetArray);
                        }
                    }

                }
            }

            // 将缓冲组中已经合并的组剔除
            int i = 0;
            GroupList bList = new GroupList();
            foreach (Group @group in bufferList.List)
            {
                if (classifiedBSubscript.Contains(i))
                {
                    i++;
                    continue;
                }
                bList.Add(group);
                i++;
            }

            // 将重新分出的分组装回去
            if (extraGroup != null)
                bList.Add(extraGroup);

            bufferGroupLists.Add(bList);

            sw.Close();
        }


        private void MergeThreeGroup(GroupList bufferList)
        {

            StreamWriter sw = new StreamWriter("log.txt", true);
            GroupList resultList;

            List<Dictionary<string, int>> resultCompare = new List<Dictionary<string, int>>();
            List<DiffThreeGroup> diffThreeGroups = new List<DiffThreeGroup>();

            Group extraGroup = null;

            int i;
            for (i = 0; i < resultGroupLists.Count; i++)
            {
                if (resultGroupLists[i].List[0].count >= MaxPeople)
                {
                    continue;
                }
                resultList = resultGroupLists[i];
                int resultSubscript = i;
                int bufferSubscript = 0;

                // 三个分组的交集的数量最多的优先级最高
                // 第三个分组的共同课程也就是三个组别的两两的交集的并集
                foreach (Group bGroup in bufferList.List)
                {

                    DiffThreeGroup diffThreeGroup = new DiffThreeGroup();
                    if (resultList.List.Count == 1)
                    {
                        continue;
                    }
                    var common =
                        resultList.List[0].Details.Intersect(bGroup.Details).Intersect(resultList.List[1].Details);


                    // 存储三个的交集
                    if (common.Count() != 0 && common.Count() != 0)
                    {
                        diffThreeGroup.Common =
                            common.ToDictionary(keyValuePair => keyValuePair.Key, keyValuePair => keyValuePair.Value);
                        diffThreeGroups.Add(diffThreeGroup);
                        diffThreeGroup.resultListSubscript = resultSubscript;
                        diffThreeGroup.bufferSubscript = bufferSubscript;
                    }

                    bufferSubscript++;
                }
            }

            // 按照共有课程最多的排序
            var sortThreeDiffGroup =
                from diffGroup in diffThreeGroups
                orderby diffGroup.CommonCount descending
                select diffGroup;


            foreach (var diffResult in sortThreeDiffGroup)
            {
                if (diffResult.CommonCount == 0 ||
                    bufferList.List[diffResult.bufferSubscript].count +
                    resultGroupLists[diffResult.resultListSubscript].Count > MaxPeople)
                    continue;
                Dictionary<string, int> fuckDictionary = new Dictionary<string, int>
                {
                    {"相同", diffResult.CommonCount},
                    {
                        "总数", bufferList.List[diffResult.bufferSubscript].count +
                              resultGroupLists[diffResult.resultListSubscript].Count
                    },
                    {"结果组人数", resultGroupLists[diffResult.resultListSubscript].Count},
                    {"缓冲组人数", bufferList.List[diffResult.bufferSubscript].count},
                    {"结果组下标", diffResult.resultListSubscript},
                    {"缓冲组下标", diffResult.bufferSubscript}
                };
                resultCompare.Add(fuckDictionary);
            }

            var mergeQuery =
                from compare in resultCompare
                orderby compare["相同"] descending, compare["总数"] descending
                select compare;

            // 输出第一次预合并结果
            foreach (Dictionary<string, int> dictionary in mergeQuery)
            {
                foreach (KeyValuePair<string, int> keyValuePair in dictionary)
                {
                    sw.Write(keyValuePair.Value + "\t");
                    Console.Write(keyValuePair.Value + "\t");
                }
                sw.WriteLine();
                Console.WriteLine();
            }

            // 合并分组

            HashSet<int> classifiedBSubscript = new HashSet<int>();
            HashSet<int> classifiedRSubscript = new HashSet<int>();
            foreach (Dictionary<string, int> dictionary in mergeQuery)
            {

                // 记录该次分组调取的下标
                int bSubscript = dictionary["缓冲组下标"];
                int rSubscript = dictionary["结果组下标"];

                // 如果该分组在之前已经被调用过了，则不再让其参与分组合并工作
                if (!classifiedBSubscript.Contains(bSubscript) && !classifiedRSubscript.Contains(rSubscript))
                {


                    if (dictionary["总数"] < MaxPeople && dictionary["总数"] > 30 && dictionary["相同"] > 6)
                    {

                        Group addedBGroup = bufferList.List[bSubscript];
                        // 将加入的第三个分组找到它的共同课程和特别课程
                        // 同时修改resultlist中的课程的共同课程和特别课程
                        foreach (DiffThreeGroup diffThreeGroup in diffThreeGroups)
                        {
                            if (diffThreeGroup.resultListSubscript == rSubscript &&
                                diffThreeGroup.bufferSubscript == bSubscript)
                            {
                                addedBGroup.Common = diffThreeGroup.Common;

                                addedBGroup.Special =
                                    (addedBGroup.Details.Except(addedBGroup.Common)).ToDictionary(e => e.Key,
                                        e => e.Value);
                                foreach (Group @group in resultGroupLists[rSubscript].List)
                                {
                                    // 重新修改结果分组中之前的两个分组的特别课程的名称，和第三个加进来的一致
                                    group.Common = diffThreeGroup.Common;
                                    group.Special =
                                        (group.Details.Except(addedBGroup.Common)).ToDictionary(e => e.Key,
                                            e => e.Value);
                                    foreach (KeyValuePair<string, string> keyValuePair in group.Special)
                                    {
                                        string oldName = null;
                                        // 找出之前的旧名字
                                        foreach (string s in group.Curriculum.CourseSet)
                                        {
                                            if (s.Contains(keyValuePair.Key))
                                            {
                                                oldName = s;
                                                break;
                                            }
                                        }

                                        // 新名字换旧名字
                                        string newName = oldName.Substring(0, oldName.Length - 1) + 1;
                                        foreach (List<CourseCell> cells in group.Curriculum.table)
                                        {
                                            foreach (CourseCell cell in cells)
                                            {
                                                if (cell.CourseName.Contains(oldName.Substring(0, 2)))
                                                {
                                                    cell.CourseName = oldName.Substring(0, oldName.Length - 1) + 1;
                                                    cell.isSpecialCourse = 1;
                                                }

                                            }
                                        }
                                        group.Curriculum.CourseSet.Remove(oldName);
                                        group.Curriculum.CourseSet.Add(newName);

                                        resultGroupLists[rSubscript].CourseSet.Remove(oldName);
                                        resultGroupLists[rSubscript].CourseSet.Add(newName);
                                    }
                                }


                                classifiedBSubscript.Add(bSubscript);
                                classifiedRSubscript.Add(rSubscript);

                                resultGroupLists[rSubscript].Add(addedBGroup, rSubscript); // 将该次分组结果存入全局变量中
                                break; // 不用再找了，已经找到
                            }
                        } // 找diffthreegroup中对应的那个
                    }
                }

                // 将缓冲组中已经合并的组剔除
                i = 0;
                GroupList bList = new GroupList();
                foreach (Group @group in bufferList.List)
                {
                    if (classifiedBSubscript.Contains(i))
                    {
                        i++;
                        continue;
                    }
                    bList.Add(group);
                    i++;
                }

                bufferGroupLists.Add(bList);

                sw.Close();
            }
        }

        /// <summary>
        /// 将所有散户编号加入结果列表中
        /// 按照“课程名称+列表下标+档次+1+散”对所有散户课程进行编号
        /// 所有按照初始化数据处理
        /// </summary>
        public void RetailProcess()
        {


            GroupList leftRetails = bufferGroupLists.Last();
            leftRetails.isResult = true;
            resultGroupLists.Add(leftRetails);
            int rSubscript = resultGroupLists.Count - 1;
            for (int i = 0; i < leftRetails.List.Count; i++)
            {
                var set = leftRetails.List[i].Curriculum.CourseSet;
                leftRetails.List[i].Special = leftRetails.List[i].Details;
                string name = "";

                foreach (List<CourseCell> cells in leftRetails.List[i].Curriculum.table)
                    foreach (var cell in cells)
                        cell.isSpecialCourse = 1;

                foreach (KeyValuePair<string, string> detail in leftRetails.List[i].Details)
                {
                    name = detail.Key + rSubscript + detail.Value + "1" + "散";
                    set.Add(name);
                    leftRetails.CourseSet.Add(name);

                }

            }
        }

        /// <summary>
        /// 根据分班情况生成合并混合班后的课程编号结果
        /// </summary>
        public void GenCourseResultNum()
        {

            foreach (GroupList resultGroupList in resultGroupLists)
            {

                // 在分班结果列表中遍历给课程重新编号
                foreach (string s in resultGroupList.CourseSet)
                {
                    string isMixed = null;
                    if (Char.IsDigit(s.Substring(s.Length - 1, 1), 0))
                    {
                        isMixed = s.Substring(s.Length - 1, 1);
                    }
                    else if (Char.IsDigit(s.Substring(s.Length - 2, 1), 0))
                    {
                        isMixed = s.Substring(s.Length - 2, 1);
                    }


                    // 如果是混合班则需要进入该分班列表内部把人数找出来
                    if (isMixed == "1")
                    {
                        int i = 1;
                        foreach (var group in resultGroupList.List)
                        {

                            if (group.Curriculum.CourseSet.Contains(s))
                            {
                                string[] num = classifiedCourses.Add(s, group.count, i);
                                string name = s.Substring(0, 2);

                                // 将运算出来的新班级编号存储到ClassDetails中
                                group.ClassDetails.Add(name, name + num[0] + num[1] + num[2]);


                                foreach (var list in group.Curriculum.table)
                                {
                                    foreach (var cell in list)
                                    {
                                        if (cell.CourseName.IndexOf(name) >= 0)
                                        {
                                            cell.CourseName = s;
                                            cell.Class = name + num[0] + num[1] + num[2];
                                        }
                                    }
                                }
                            }
                            i++;
                        }


                    }
                    else //  否则直接将普通班的人数和原编号加进去
                    {
                        string[] num = classifiedCourses.Add(s, resultGroupList.Count);
                        foreach (var group in resultGroupList.List)
                        {
                            if (group.Curriculum.CourseSet.Contains(s))
                            {
                                string name = s.Substring(0, 2);

                                // 将运算出来的新班级编号存储到ClassDetails中
                                group.ClassDetails.Add(name, name + num[0] + num[1] + num[2]);

                                foreach (var list in group.Curriculum.table)
                                {
                                    foreach (var cell in list)
                                    {
                                        if (cell.CourseName.IndexOf(name) >= 0)
                                        {
                                            cell.CourseName = s;
                                            cell.Class = name + num[0] + num[1] + num[2];
                                        }
                                    }
                                }
                            }

                        }

                    }
                }

            }

        }

        private void UpdateCourseTableForDiffLevel()
        {
            foreach (GroupList resultGroupList in resultGroupLists)
            {
                foreach (Group @group in resultGroupList.List)
                {
                    string level;
                    group.Details.TryGetValue("物理", out level);
                    if (level == "学")
                    {
                        DelCourse("物理", group.Curriculum.table);
                    }
                    group.Details.TryGetValue("化学", out level);
                    if (level == "学")
                    {
                        DelCourse("化学", group.Curriculum.table);
                    }
                    group.Details.TryGetValue("政治", out level);
                    if (level == "学")
                    {
                        DelCourse("政治", group.Curriculum.table);
                    }
                    group.Details.TryGetValue("历史", out level);
                    if (level == "学")
                    {
                        DelCourse("历史", group.Curriculum.table);
                    }
                    group.Details.TryGetValue("地理", out level);
                    if (level == "学")
                    {
                        DelCourse("地理", group.Curriculum.table);
                    }
                }
            }
        }

        private void DelCourse(string name, List<List<CourseCell>> table)
        {
            switch (name)
            {
                case "物理":
                    if (table[2][7].CourseName.Contains("物理"))
                    {
                        table[2][7].Class = null;
                        table[2][7].CourseName = "可调";
                    }
                    break;
                case "化学":
                    if (table[1][1].CourseName.Contains("化学"))
                    {
                        table[1][1].CourseName = "可调";
                        table[1][1].Class = null;
                    }
                    break;
                case "历史":
                    if (table[0][8].CourseName.Contains("历史"))
                    {
                        table[0][8].CourseName = "可调";
                        table[0][8].Class = null;
                    }
                    break;
                case "地理":
                    if (table[4][6].CourseName.Contains("地理"))
                    {
                        table[4][6].CourseName = "可调";
                        table[4][6].Class = null;
                    }
                    break;
                case "政治":
                    if (table[3][8].CourseName.Contains("政治"))
                    {
                        table[3][8].CourseName = "可调";
                        table[3][8].Class = null;
                    }
                    break;

            }

        }



        /// <summary>
        /// 课程和教室的数据结构建立
        /// </summary>
        private void GetClassAndCourses()
        {
            for (int j = 0; j < BetterEnergyTable.CompareList.Count; j++)
            {
                GroupList list = BetterEnergyTable.CompareList[j];
                GroupListClass groupList = new GroupListClass();

                // 首先找出共同课程对应的班级编号
                // 再找出每个分组自己的特别课程有哪些
                for (int i = 0; i < list.List.Count; i++)
                {

                    foreach (List<CourseCell> cells in list.List[i].Curriculum.table)
                    {
                        foreach (CourseCell cell in cells)
                        {
                            if (cell.Class == null)
                                continue;
                            if (!(cell.isSpecialCourse ==1)
                                && !groupList.CommonClass.ContainsKey(cell.Class))
                            {
                                groupList.CommonClass.Add(cell.Class, j + 101);
                            }

                            else if (cell.isSpecialCourse==1 && !groupList.SpecialList.ContainsKey(cell.Class))
                            {
                                groupList.SpecialList.Add(cell.Class, 0);
                            }
                        }

                    }

                }
                GroupListClasses.Add(groupList);
            }
        }

        /// <summary>
        /// 分教室
        /// </summary>
        private void ClassifyClassromm()
        {

            for (int i = 0; i < GroupListClasses.Count; i++)
            {
                HashSet<string> chosedCourse = new HashSet<string>();
                List<string> allCourses = new List<string>(GroupListClasses[i].SpecialList.Keys);
                foreach (string s in allCourses)
                {
                    // 如果这个课程班没有分配教室并且该课程还没有分配当前分组编号+1教室
                    if (GroupListClasses[i].SpecialList[s] == 0
                        && !chosedCourse.Contains(s.Substring(0, 2)))
                    {
                        // 这个课程就给分配当前分组编号+1教室
                        GroupListClasses[i].SpecialList[s] = i + 101;
                        // 遍历所有的groupList将对应班级教室修改
                        ChangeClassroom(s, i + 101);
                        // 将该课程加入已经分配该班对应教室集合中
                        chosedCourse.Add(s.Substring(0, 2));
                    }
                    else
                    {
                        // 否则就暂时先不管该班级
                    }
                }
                //if (chosedCourse.Count*2 != allCourses.Count)
                //{
                //    throw new Exception("分配课程数据出错！");
                //}
            }

            // 剩下的没有分配课程的我们就单独开班好了
            int initial = 200;
            HashSet<string> chosedCourses;
            do
            {
                chosedCourses = new HashSet<string>();
                foreach (GroupListClass listClass in GroupListClasses)
                {
                    List<string> allCourses = new List<string>(listClass.SpecialList.Keys);
                    foreach (string course in allCourses)
                    {

                        if (listClass.SpecialList[course] == 0)
                        {
                            if (!chosedCourses.Contains(course.Substring(0, 2)))
                            {
                                // 给没有编号的课程单独开班
                                listClass.SpecialList[course] = initial;
                                ChangeClassroom(course, initial);
                                chosedCourses.Add(course);
                            }
                        }
                    }
                }
                initial++;

            } while (chosedCourses.Count > 0);

            // 将教室分配结果写入各个group中
            for (int i = 0; i < BetterEnergyTable.CompareList.Count; i++)
            {
                foreach (Group @group in BetterEnergyTable.CompareList[i].List)
                {
                    foreach (List<CourseCell> cells in group.Curriculum.table)
                    {
                        foreach (CourseCell cell in cells)
                        {
                            if (cell.Class != null)
                            {
                                int classroomNumber;
                                if (cell.isSpecialCourse == 1)
                                {

                                    GroupListClasses[i].SpecialList.TryGetValue(cell.Class, out classroomNumber);
                                    if (classroomNumber != 0)
                                    {
                                        cell.ClassroomNumber = classroomNumber;
                                    }
                                }
                                else
                                {
                                    GroupListClasses[i].CommonClass.TryGetValue(cell.Class, out classroomNumber);
                                    if (classroomNumber != 0)
                                    {
                                        cell.ClassroomNumber = classroomNumber;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private void ChangeClassroom(string className, int number)
        {
            foreach (GroupListClass listClass in GroupListClasses)
            {
                List<string> allCourses = new List<string>(listClass.SpecialList.Keys);
                foreach (string course in allCourses)
                {

                    if (course == className)
                    {
                        //if (listClass.SpecialList[course] != 0)
                        //{
                        //    throw new Exception("该课程已经被分班了，出问题了");
                        //}
                        listClass.SpecialList[course] = number;
                    }
                }
            }
        }


        /// <summary>
        /// 交换一个班级当天相同类型的所有课程保留最后的结果
        /// </summary>
        private void ExchangeForGroupClass()
        {
            // 计算能量值
            double rawSum = BetterEnergyTable.sum;
            // 交换课程

            for (int day = 0; day < 5; day++) // 交换每一天的课程
            {
                // 遍历交换每个班级的课程
                for (int groupClassSubscript = 0; groupClassSubscript < resultGroupLists.Count; groupClassSubscript++)
                {
                    // 换了一个班级之后，用来记录所有调换课程的能量表全部清空

                    //遍历交换任意两门课程

                    for (int i = 0; i < 5 * CourseNumADay; i++)
                    {

                        for (int j = i + 1; j < 5 * CourseNumADay; j++)
                        {
                            int day1 = i / CourseNumADay;
                            int day2 = j / CourseNumADay;
                            int period1 = i % CourseNumADay;
                            int period2 = j % CourseNumADay;

                            // 只有相同类型的课程（共同课程）才可以交换
                            // 每次交换完成后都要重新计算当天的每一科目上的次数
                            //???只有满足条件的课程才可交换
                            //??半混班也可交换
                            EnergyTable exchangedEnergyTable = new EnergyTable(BetterEnergyTable.CompareList);
                            if (!CannotChangeCourses(exchangedEnergyTable.CompareList[groupClassSubscript].List, day1, day2,period1, period2, true))
                                {
                                    exchangedEnergyTable.ExchangeTwoDayCourse(groupClassSubscript, day1, period1, day2, period2);
                                    exchangedEnergyTable.GetCourse();
                                    exchangedEnergyTable.CalculateEnergy();


                                    if (rawSum > exchangedEnergyTable.sum)
                                    {
                                        BetterEnergyTable = new EnergyTable(exchangedEnergyTable.CompareList);
                                        BetterEnergyTable.GetCourse();
                                        BetterEnergyTable.CalculateEnergy();
                                        rawSum = BetterEnergyTable.sum;
                                        Console.WriteLine(rawSum);

                                    }

                                }   
                            }
                         
                        }
                }
            }


        }

        /// <summary>
        /// 额外增加教室来减少能量值
        /// </summary>
        public void AddNewClassroomForTeacher(string course1, string course2)
        {


            List<int[]> conflictLocation = new List<int[]>();
            string disciplineName = course1.Substring(0, 2);
            for (int i = 0; i < BetterEnergyTable.Count(); i++)
            {
                for (int j = 0; j < BetterEnergyTable[i].Count(); j++)
                {
                    List<string> name;
                    BetterEnergyTable[i][j].TryGetValue(disciplineName, out name);
                    if (name != null && name.Contains(course1) && name.Contains(course2))
                    {
                        conflictLocation.Add(new[] {i, j});
                    }
                }
            }

            List<int[]> goodConflictList;
            // 尝试将course1放入额外教室中
            int CourseCount = conflictLocation.Count; // 需要转移的课程数量
            // 创建额外教室，相当于添加一个新的GroupList
            GroupList groupList = new GroupList();
            Group group = new Group();

            do
            {
                GenNeighbourState();
                BetterEnergyTable = new EnergyTable(BetterEnergyTable.CompareList);
                BetterEnergyTable.GetCourse();
                BetterEnergyTable.CalculateEnergy();
                ExchangeForGroupClass();

                // 找出要在一起的两门课发生冲突的课程位置
                EnergyTable exchangedEnergyTable = BetterEnergyTable;



                // 遍历放置抽出的班级，查看是否和当前上课的班级构成存在冲突
                HashSet<int> originalClassNameSet = new HashSet<int>();

                // 统计每个位置发生冲突的分组个数以及具体的课程班级名称
                List<int[]> conflictList = new List<int[]>();

                HashSet<int> bigClassSet = new HashSet<int>();

                foreach (int i1 in classifiedCourses.NewCourseIndex[course1])
                    bigClassSet.Add(i1/100*100);

                // 修改group中的课程内容
                // 只保留抽出的班级那天的班级
                for (int i = 0; i < group.Curriculum.table.Count; i++)
                {

                    for (int j = 0; j < group.Curriculum.table[i].Count; j++)
                    {
                        // 周五最后两节课不能动
                        if (i != 4 && (j != 7 || j != 8))
                        {
                            originalClassNameSet = new HashSet<int>();
                            // 遍历获取该位置出现过的所有的小分组名单 
                            foreach (KeyValuePair<string, List<string>> pair in BetterEnergyTable[i][j])
                            {
                                foreach (string s in pair.Value)
                                {
                                    foreach (int i1 in classifiedCourses.NewCourseIndex[s])
                                    {
                                        originalClassNameSet.Add(i1);
                                    }
                                }
                            }

                            // 若当期班级构成的分组没有在分组集合中，则说明可以插进去

                            // 首先对非混合班的情况进行判断
                            // 如果没有非混合班发生冲突
                            if (!classifiedCourses.NewCourseIndex[course1].Intersect(originalClassNameSet).Any())
                            {
                                // 记录非混合班冲突的个数以及具体分组编号
                                int[] classSet = new int[3];

                                classSet[0] = i;
                                classSet[1] = j;
                                classSet[2] = originalClassNameSet.Intersect(bigClassSet).Count();
                                conflictList.Add(classSet);
                            }



                        }

                        //// 当混合班不冲突且非混合班也不冲突的情况下才可以插入
                        //if (!classifiedCourses.NewCourseIndex[course1].Intersect(originalClassNameSet).Any()
                        //    && !bigClassSet.Intersect(originalClassNameSet).Any())
                        //{
                        //    //// 将新的插进去
                        //    //group.Curriculum.table[i][j].Class = course1;
                        //    //List<string> newList;
                        //    //exchangedEnergyTable[i][j].TryGetValue(location[2], out newList);
                        //    //newList.Add(course);
                        //    //// 将这门课从之前的地方抹去
                        //    //classList.Remove(course);
                        //    //// 重新计算能量值
                        //    //exchangedEnergyTable.CalculateEnergy(0.3, 0.7);

                        //    //// 若新的能量值小于等于原来的，即可认为接受新的能量值
                        //    //if (exchangedEnergyTable.sum <= BetterEnergyTable.sum)
                        //    //{
                        //    //    // 修改抽出班级所在分组的课程表
                        //    //    foreach (int i1 in classifiedCourses.NewCourseIndex[course])
                        //    //    {

                        //    //    }
                        //    //}

                        //}

                    }


                }

                // 开始尝试插入课程

                // 判断是否可以不用减少课程就能够直接 插入课程
                goodConflictList = conflictList.Where(intse => intse[2] == 0).ToList();
                if (goodConflictList.Count >= conflictLocation.Count)
                {
                    // 直接插入当前班级，不需要调动任何位置
                    for (int m = 0; m < conflictLocation.Count; m++)
                    {

                        // 找出该班级包含的具体分组的课程表
                        foreach (int i in classifiedCourses.NewCourseIndex[course1])
                        {
                            int bigclass = i/100;
                            int groupNumber = i%100 - 1;
                            // 将课程一一转移到新的位置上去
                            // 额外教室的地方用来存储

                            var cell = exchangedEnergyTable.CompareList[bigclass].List[groupNumber].Curriculum.
                                table[conflictLocation[m][0]][conflictLocation[m][1]];

                            group.Curriculum.table[goodConflictList[m][0]][goodConflictList[m][1]] = cell;

                            cell = exchangedEnergyTable.CompareList[bigclass].List[groupNumber].Curriculum.
                                table[goodConflictList[m][0]][goodConflictList[m][1]];

                            exchangedEnergyTable.CompareList[bigclass].List[groupNumber].Curriculum.
                                table[conflictLocation[m][0]][conflictLocation[m][1]] = cell;

                            exchangedEnergyTable.CompareList[bigclass].List[groupNumber].Curriculum.
                                table[goodConflictList[m][0]][goodConflictList[m][1]].Class = null;
                            exchangedEnergyTable.CompareList[bigclass].List[groupNumber].Curriculum.
                                table[goodConflictList[m][0]][goodConflictList[m][1]].CourseName = "可调";

                            Console.WriteLine("新教室的上课时间为:" + goodConflictList[m][0] + goodConflictList[m][1]);
                        }
                    }
                }
            } while (goodConflictList.Count < conflictLocation.Count);

            groupList.Add(group);
            BetterEnergyTable.CompareList.Add(groupList);
            // 确定两个混合班最后在一起了之后不能够加入他们俩的非混合班
            List<string> cannotTogether = new List<string>();
            for (int i = 0; i < conflictLocation.Count; i++)
            {
                int[] intse = goodConflictList[i];
                List<string> list;
                BetterEnergyTable[intse[0]][intse[1]].TryGetValue(course1.Substring(0, 2), out list);
                if (list.Count <= 0) continue;
                cannotTogether.AddRange(list.Where(s => s.Substring(3, 1) == "0"));
            }

            foreach (List<CourseCell> cells in group.Curriculum.table)
            {
                foreach (CourseCell cell in cells)
                {
                    cell.CourseName = cell.CourseName ?? "可调";
                }
            }

            foreach (string s in cannotTogether)
            {
                Console.Write(s + "  ");
            }

        }

        /// <summary>
        /// 额外增加教室来减少能量值
        /// </summary>
        private void UseNewClassroomToDecreaseEnergyValue()
        {
            // 找出当前能量值最高位置的课程
            string[] location = new string[3];
            List<string> classList;
            EnergyTable exchangedEnergyTable = new EnergyTable(BetterEnergyTable.CompareList);
            exchangedEnergyTable.GetCourse();
            location = exchangedEnergyTable.CalculateEnergy();

            exchangedEnergyTable[int.Parse(location[0])][int.Parse(location[1])].TryGetValue(location[2], out classList);

            // 遍历抽出能量最高的课程班级
            // 优先抽出学混合班
            if (classList == null)
            {
                throw new Exception("出问题了！！");
            }
            classList.Sort();
            classList.Reverse();
            foreach (string course in classList)
            {
                // 创建额外教室，相当于添加一个新的GroupList
                GroupList groupList = new GroupList();
                Group group = new Group();
                groupList.Add(group);
                // 修改group中的课程内容
                // 只保留抽出的班级那天的班级
                for (int i = 0; i < group.Curriculum.table.Count; i++)
                {

                    for (int j = 0; j < group.Curriculum.table[i].Count; j++)
                    {
                        // 周五最后两节课不能动
                        if (i != 4 && (j != 7 || j != 8))
                        {
                            // 遍历放置抽出的班级，查看是否和当前上课的班级构成存在冲突
                            //if (i == int.Parse(location[0]))
                            {
                                HashSet<int> originalClassNameSet = new HashSet<int>();
                                // 遍历获取该位置出现过的所有的小分组名单 
                                foreach (KeyValuePair<string, List<string>> pair in BetterEnergyTable[i][j])
                                {
                                    foreach (string s in pair.Value)
                                    {
                                        foreach (int i1 in classifiedCourses.NewCourseIndex[s])
                                        {
                                            originalClassNameSet.Add(i1);
                                        }
                                    }
                                }

                                // 若当期班级构成的分组没有在分组集合中，则说明可以插进去
                                if (!classifiedCourses.NewCourseIndex[course].Intersect(originalClassNameSet).Any())
                                {
                                    // 将新的插进去
                                    group.Curriculum.table[i][j].Class = course;
                                    List<string> newList;
                                    exchangedEnergyTable[i][j].TryGetValue(location[2], out newList);
                                    newList.Add(course);
                                    // 将这门课从之前的地方抹去
                                    classList.Remove(course);
                                    // 重新计算能量值
                                    exchangedEnergyTable.CalculateEnergy();

                                    // 若新的能量值小于等于原来的，即可认为接受新的能量值
                                    if (exchangedEnergyTable.sum <= BetterEnergyTable.sum)
                                    {
                                        // 修改抽出班级所在分组的课程表
                                        foreach (int i1 in classifiedCourses.NewCourseIndex[course])
                                        {

                                        }
                                    }

                                }

                            }
                            //else
                            {
                                group.Curriculum.table[i][j].CourseName = "!";
                            }

                        }



                    }
                }
            }



        }

        /// <summary>
        /// 每调整一节课程，需要遍历所有的分组，相同的课程全部都要进行调整
        /// </summary>
        private void ExchangeForClassifiedGroupClass()
        {
            // 计算能量值
            double rawSum = BetterEnergyTable.sum;
            // 交换课程

            for (int day = 0; day < 5; day++) // 交换每一天的课程
            {
                // 遍历交换每个班级的课程
                for (int groupClassSubscript = 0; groupClassSubscript < resultGroupLists.Count; groupClassSubscript++)
                {
                    EnergyTable exchangedEnergyTable;

                    //遍历交换任意两门课程
                    for (int i = 0; i < 5; i++)
                    {
                        for (int j = 0; j < CourseNumADay; j++)
                        {
                            for (int k = j + 1; k < CourseNumADay; k++)
                            {
                                int day1 = i;
                                int day2 = i;
                                int period1 = j;
                                int period2 = k;

                                // 只有相同类型的课程（共同课程）才可以交换

                                exchangedEnergyTable = new EnergyTable(BetterEnergyTable.CompareList);



                                // 正常的对换
                                if (!CannotChangeCourses(exchangedEnergyTable.CompareList[groupClassSubscript].List, day1, day2, period1, period2, false)


                                               && !CannotChangeCourses(exchangedEnergyTable.CompareList[groupClassSubscript].List, day1, day2, period2, period2, false))

                                {
                                    string course1 =
                                        exchangedEnergyTable.CompareList[groupClassSubscript].
                                            List[0].Curriculum.table[day1][period1].Class;
                                    string course2 =
                                        exchangedEnergyTable.CompareList[groupClassSubscript].
                                            List[0].Curriculum.table[day2][period2].Class;


                                    exchangedEnergyTable.ExchangeTwoDayCourseForClassified
                                        (groupClassSubscript, day1, period1, day2, period2, course1, course2);
                                    exchangedEnergyTable.GetCourse();
                                    exchangedEnergyTable.CalculateEnergy();
                                    Console.WriteLine(exchangedEnergyTable.sum);

                                    if (rawSum > exchangedEnergyTable.sum)
                                    {
                                        BetterEnergyTable = new EnergyTable(exchangedEnergyTable.CompareList);
                                        BetterEnergyTable.GetCourse();
                                        BetterEnergyTable.CalculateEnergy();
                                        rawSum = BetterEnergyTable.sum;
                                        Console.WriteLine(rawSum);

                                    }

                                }
                            }

                        }
                    }


                }
            }




        }

        private bool CannotChangeCourses(
            List<Group> classGroup, int day1, int day2, int period1, int period2, bool isIgnoreSomeCourses = true)
        {
            foreach (Group list in classGroup)
            {
				CourseCell exchangeCell1 = list.Curriculum.table[day1][period1];
				CourseCell exchangeCell2 = list.Curriculum.table[day2][period2];

                if (exchangeCell1.isSpecialCourse==1 || exchangeCell2.isSpecialCourse==1) return true;

                if ((exchangeCell1.isSpecialCourse == 2 && exchangeCell2.isSpecialCourse != 2)
                    || (exchangeCell2.isSpecialCourse == 2 && exchangeCell1.isSpecialCourse != 2)) return true;

                if (exchangeCell1.CourseName == "!" || exchangeCell2.CourseName == "!") return true;

                if (!CanCourseCellExchangeByPosition(exchangeCell1, exchangeCell2)) return true;

                string course=exchangeCell1.CourseName.Substring(0, 2);
                int count;
                list.Curriculum.everydayCourseCount[day1].TryGetValue(course, out count);
                if (count >= 2) return true;

            }
            return false;
        }

        /// <summary>
        /// 产生领域解
        /// 方法：交换任意两门课程（不在同一天的）
        /// </summary>
        private bool GenNeighbourState()
        {
            EnergyTable exchangedEnergyTable = new EnergyTable(BetterEnergyTable.CompareList);
            double rawSum = BetterEnergyTable.sum;

            Console.WriteLine("初始能量值为" + rawSum);
            for (int i = 0; i < BetterEnergyTable.CompareList.Count; i++)
            {
                // 退火次数

                for (int j = 0; j < 50; j++)
                {
                    Thread.Sleep(20);
                    Random random = new Random((int) DateTime.Now.Ticks & 0x0000FFFF);

                    int groupClassSubscript = i;
                    int day1 = random.Next(5);
                    int period1 = random.Next(8);

                    int day2 = random.Next(5);
                    int period2 = random.Next(8);

                    /**
                     * 容易出现的问题
                     * 在改变课程了之后，需要重新获取课程数据
                     * 这个时候不能直接在原有的对象上获取
                     * 需要新建一个对象，将课程数据传进去才行
                     * */

                  if (!CannotChangeCourses(exchangedEnergyTable.CompareList[groupClassSubscript].List, day1, day2, period1, period2, true))

                    {
                        string c = exchangedEnergyTable.ExchangeTwoDayCourse(groupClassSubscript, day1, period1, day2, period2);
                        if (c != "" && !CanCellInThisPosition(c.Substring(0,2),int.Parse(c.Substring(2,1))))
                        {
                            throw new Exception("出问题了！");
                        }
                    }


                }

            }

            BetterEnergyTable = new EnergyTable(exchangedEnergyTable.CompareList);
            BetterEnergyTable.GetCourse();
            BetterEnergyTable.CalculateEnergy();
            //Console.WriteLine(BetterEnergyTable.sum == exchangedEnergyTable.sum);
            rawSum = BetterEnergyTable.sum;
            Console.WriteLine("退火升高的最终能量为" + BetterEnergyTable.sum + "\n");
            Console.WriteLine("退火升高的最终能量为" + exchangedEnergyTable.sum + "\n");
            return true;

        }



        public void PrintCourseTableByGroup(Group group)
        {
            string result = null;
            foreach (List<CourseCell> cells in group.Curriculum.table)
            {
                foreach (CourseCell cell in cells)
                {
                    if (cell.Class == null)
                    {
                        if (cell.CourseName == "体育"
                            || cell.CourseName == "音乐"
                            || cell.CourseName == "美术")
                        {
                            cell.Class = cell.CourseName;
                            Console.Write(cell.CourseName + "  ");
                        }

                    }
                    else
                    {
                        Console.Write(cell.Class + "  ");
                    }

                }
                Console.WriteLine();
            }
        }

        public void PrintCourseTableByDiscipline(string discipline)
        {
            for (int i = 0; i < BetterEnergyTable.Count; i++)
            {
                List<Dictionary<string, List<string>>> list = BetterEnergyTable[i];
                foreach (Dictionary<string, List<string>> dictionary in list)
                {
                    List<string> classList;
                    if (dictionary.TryGetValue(discipline, out classList))
                    {
                        foreach (string s in classList)
                        {
                            Console.Write(s + " ");
                        }
                    }
                    Console.WriteLine();

                }
                Console.WriteLine("下一天");
            }
        }

        public void GetGroupedStudentList(string filePath)
        {
            //try
            //{
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                IWorkbook book = new HSSFWorkbook(fs);

                for (int j = 0; j < book.NumberOfSheets; j++)
                {
                    ISheet sheet = book.GetSheetAt(j);
                    int rFirst = sheet.FirstRowNum;
                    int rLast = sheet.LastRowNum;

                    // 获取成绩的标题
                    IRow firstRow = sheet.GetRow(0);
                    List<string> scoreTitle = new List<string>();
                    for (int i = 14; i < firstRow.LastCellNum; i++)
                    {
                        scoreTitle.Add(firstRow.GetCell(i).ToString());
                    }

                    for (int i = rFirst + 1; i < rLast + 1; i++)
                    {
                        IRow ir = sheet.GetRow(i);

                        Student student = new Student
                        {
                            Id = ir.GetCell(0).ToString(),
                            Name = ir.GetCell(1).ToString(),
                            Sex = ir.GetCell(2).ToString(),
                            Chinese = ir.GetCell(4).ToString(),
                            Math = ir.GetCell(5).ToString(),
                            English = ir.GetCell(6).ToString(),
                            Physics = ir.GetCell(10).ToString(),
                            Chemistry = ir.GetCell(11).ToString(),
                            Biology = ir.GetCell(12).ToString(),
                            Politics = ir.GetCell(7).ToString(),
                            History = ir.GetCell(8).ToString(),
                            Geography = ir.GetCell(9).ToString(),
                            Computer = ir.GetCell(13).ToString()
                        };

                        for (int k = 14; k < ir.LastCellNum; k++)
                        {
                            student.scoreDetails.Add(scoreTitle[k - 14], ir.GetCell(k).NumericCellValue);
                        }
                        resultGroupLists[j].StuList.Add(student);
                    }
                }
            }
            //}
            //catch (Exception e)
            //{

            //    Console.WriteLine(e.ToString());
            //    Console.ReadKey();
            //}
            for (int i = 0; i < resultGroupLists.Count; i++)
            {
                // 如果是一个完全纯班
                // 直接将班级数据输进去
                if (resultGroupLists[i].List.Count == 1)
                {
                    for (int j = 0; j < resultGroupLists[i].List[0].count; j++)
                    {
                        for (int k = 0; k < resultGroupLists[i].StuList.Count; k++)
                        {
                            Student student = resultGroupLists[i].StuList[k];
                            student.Biology = resultGroupLists[i].List[0].ClassDetails["生物"];
                            student.Chemistry = resultGroupLists[i].List[0].ClassDetails["化学"];
                            student.Chinese = resultGroupLists[i].List[0].ClassDetails["语文"];
                            student.Computer = resultGroupLists[i].List[0].ClassDetails["通技"];
                            student.English = resultGroupLists[i].List[0].ClassDetails["英语"];
                            student.Geography = resultGroupLists[i].List[0].ClassDetails["地理"];
                            student.History = resultGroupLists[i].List[0].ClassDetails["历史"];
                            student.Math = resultGroupLists[i].List[0].ClassDetails["数学"];
                            student.Physics = resultGroupLists[i].List[0].ClassDetails["物理"];
                            student.Politics = resultGroupLists[i].List[0].ClassDetails["政治"];
                        }

                    }
                }
                else // 需要确保全部相符才能匹配
                {
                    foreach (Group @group in resultGroupLists[i].List)
                    {
                        for (int j = 0; j < resultGroupLists[i].StuList.Count; j++)
                        {
                            Student student = resultGroupLists[i].StuList[j];
                            if (student.Biology == group.ClassDetails["生物"].Substring(2, 1)
                                && student.Chemistry == group.ClassDetails["化学"].Substring(2, 1)
                                && student.Chinese == group.ClassDetails["语文"].Substring(2, 1)
                                && student.Computer == group.ClassDetails["通技"].Substring(2, 1)
                                && student.English == group.ClassDetails["英语"].Substring(2, 1)
                                && student.Geography == group.ClassDetails["地理"].Substring(2, 1)
                                && student.History == group.ClassDetails["历史"].Substring(2, 1)
                                && student.Math == group.ClassDetails["数学"].Substring(2, 1)
                                && student.Physics == group.ClassDetails["物理"].Substring(2, 1)
                                && student.Politics == group.ClassDetails["政治"].Substring(2, 1))
                            {
                                student.Biology = group.ClassDetails["生物"];
                                student.Chemistry = group.ClassDetails["化学"];
                                student.Chinese = group.ClassDetails["语文"];
                                student.Computer = group.ClassDetails["通技"];
                                student.English = group.ClassDetails["英语"];
                                student.Geography = group.ClassDetails["地理"];
                                student.History = group.ClassDetails["历史"];
                                student.Math = group.ClassDetails["数学"];
                                student.Physics = group.ClassDetails["物理"];
                                student.Politics = group.ClassDetails["政治"];
                            }

                        }
                    }

                }
            } // end for resultGroupList


        }

        public void GetMixedGroupList(string filePath,bool isHalfMixed)
        {
            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                IWorkbook book = new HSSFWorkbook(fs);
                resultGroupLists = new List<GroupList>();


                ISheet sheet = book.GetSheetAt(0);
                ISheet stuSheet = book.GetSheetAt(1);

                GroupList groupList = new GroupList(true);
                
                int rFirst = sheet.FirstRowNum;
                int rLast = sheet.LastRowNum;

                for (int i = rFirst + 1; i < rLast + 1; i++)
                {
                    IRow ir = sheet.GetRow(i);


                    // 如果当前读取的序号大于目前已经有的分组个数
                    // 结算旧的分组数据
                    // 添加新分组
                    if (ir.GetCell(0).NumericCellValue > resultGroupLists.Count)
                    {
                        resultGroupLists.Add(groupList);
                        groupList = new GroupList(true);
                    }

                    // 添加该分组的details数据
                    Dictionary<string, string> details = new Dictionary<string, string>();
                    for (int j = 1; j < ir.LastCellNum - 1; j++)
                    {
                        string courseName = ir.GetCell(j).ToString().Substring(0, 2);
                        details.Add(courseName, ir.GetCell(j).ToString());
                    }

                    // 将group添加到当前groupList中
                    Group group = new Group();
                    group.Curriculum = new Curriculum();
                    group.Details = details;
                    group.count = Convert.ToInt32(ir.GetCell(ir.LastCellNum - 1).NumericCellValue);
                    groupList.Add(group);

                    foreach (KeyValuePair<string, string> pair in details)
                    {
                        if (studentAmountEachClass.ContainsKey(pair.Value))
                            studentAmountEachClass[pair.Value] += group.count;
                        else studentAmountEachClass.Add(pair.Value, group.count);
                    }
                }

                resultGroupLists.Add(groupList);

                for (int i = 0; i < resultGroupLists.Count; i++)
                {
                    GroupList list = resultGroupLists[i];
                    foreach (Group @group in list.List)
                    {
                        foreach (KeyValuePair<string, string> detail in group.Details)
                        {
                            if (detail.Value.Substring(3, 1) == "0")
                            {
                                group.Common.Add(detail.Key, detail.Value);
                            }
                            else group.Special.Add(detail.Key, detail.Value);
                        }

                        // 获得每个分组的courseSet
                        foreach (KeyValuePair<string, string> pair in group.Common)
                        {
                            group.Curriculum.CourseSet.Add(pair.Value);
                        }
                        foreach (KeyValuePair<string, string> pair in group.Special)
                        {
                            group.Curriculum.CourseSet.Add(pair.Value);
                        }
                    }

                    // 获得list的courseSet
                    foreach (Group @group in list.List)
                    {
                        list.CourseSet.UnionWith(group.Curriculum.CourseSet);
                    }
                    sheet = null;

                    if (!isHalfMixed) ChangeClassNameByClass(list);
                    
                }

                // 添加相对应的学生到stuList中
                rFirst = stuSheet.FirstRowNum;
                rLast = stuSheet.LastRowNum;

                // 获取成绩的标题
                IRow firstRow = stuSheet.GetRow(0);
                List<string> scoreTitle = new List<string>();
                for (int i = 14; i < firstRow.LastCellNum; i++)
                {
                    scoreTitle.Add(firstRow.GetCell(i).ToString());
                }

                for (int i = rFirst + 1; i < rLast + 1; i++)
                {
                    IRow ir = stuSheet.GetRow(i);

                    Student student = new Student
                    {
                        Id = ir.GetCell(1).ToString(),
                        Name = ir.GetCell(2).ToString(),
                        Sex = ir.GetCell(3).ToString(),
                        Chinese = ir.GetCell(4).ToString(),
                        Math = ir.GetCell(5).ToString(),
                        English = ir.GetCell(6).ToString(),
                        Physics = ir.GetCell(10).ToString(),
                        Chemistry = ir.GetCell(11).ToString(),
                        Biology = ir.GetCell(12).ToString(),
                        Politics = ir.GetCell(7).ToString(),
                        History = ir.GetCell(8).ToString(),
                        Geography = ir.GetCell(9).ToString(),
                        Computer = ir.GetCell(13).ToString()
                    };

                    for (int k = 14; k < ir.LastCellNum; k++)
                    {
                        student.scoreDetails.Add(scoreTitle[k - 14], ir.GetCell(k).NumericCellValue);
                    }
                    resultGroupLists[int.Parse(ir.GetCell(0).ToString())].StuList.Add(student);
                }
            }
        }

        private void ChangeClassNameByClass(GroupList list)
        {
            // 修改group中课表的Class
            foreach (Group @group in list.List)
            {
                foreach (List<CourseCell> cells in group.Curriculum.table)
                {
                    foreach (CourseCell cell in cells)
                    {
                        foreach (string s in group.Curriculum.CourseSet)
                        {
                            if (s.Substring(0, 2) == cell.CourseName)
                            {
                                cell.Class = s;
                                cell.isSpecialCourse = 0;
                                if (s.Substring(3, 1) == "1")
                                {
                                    cell.isSpecialCourse = 1;
                                }
                                break;
                            }
                        }
                    }
                }
            }
        }

        // 读取之前输入的课程表数据
        internal void RecoverCourseTable(string folderPath)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(folderPath);
            foreach (FileInfo fileInfo in dirInfo.GetFiles())
            {
                // 通过文件名获取分组序号
                string[] names = fileInfo.Name.Split('.');
                int groupListNum = int.Parse(names[1]);
                int groupNum = int.Parse(names[2]);

                FileStream stream = new FileStream(folderPath + "/" + fileInfo.Name, FileMode.Open);
                StreamReader sr = new StreamReader(stream);
                // 将课程表输入
                foreach (var cells in resultGroupLists[groupListNum].List[groupNum].Curriculum.table)
                {
                    string[] courses = sr.ReadLine().Split(' ');
                    int i = 0;
                    foreach (CourseCell cell in cells)
                    {
                        cell.CourseName = courses[i];
                        i++;
                    }
                }
                sr.Close();
            }
        }

        /// <summary>
        /// 开始调整半混班
        /// </summary>
        public void ManualProcessRetails(string[] courses)
        {
            // 回到resultGroupLists中，将对应的分组对应班级以及课程表进行修改
            BetterEnergyTable = new EnergyTable(resultGroupLists);
            foreach (GroupList list in BetterEnergyTable.CompareList)
            {
                // 修改group中课表的Class
                foreach (Group @group in list.List)
                {
                    foreach (List<CourseCell> cells in group.Curriculum.table)
                    {
                        foreach (CourseCell cell in cells)
                        {
                            foreach (string s in group.Curriculum.CourseSet)
                            {
                                if (s.Substring(0, 2) == cell.CourseName)
                                {
                                    cell.Class = s;
                                    cell.isSpecialCourse = 0;
                                    if (s.Substring(3, 1) == "1")
                                    {
                                        cell.isSpecialCourse = 1;
                                    }
                                    else if (s.Contains("_"))
                                    {
                                        cell.isSpecialCourse = 2;
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
                
            }

            if (courses != null) ExchangeHalfClass(courses[0], courses[1]);
            else
            {
                BetterEnergyTable.GetCourse();
                BetterEnergyTable.CalculateEnergy();
            }

            // 将分班过后的课程班级数据进行收集整理
            GetClassAndCourses();
            // 给每个大类分教室
            ClassifyClassromm();
        }

        private void ExchangeHalfClass(string courseName1, string courseName2)
        {
            // 找到半混班的位置，计算所有半混班位置的能量值
            BetterEnergyTable.GetCourse();
            BetterEnergyTable.CalculateEnergy();
            double rawSum = BetterEnergyTable.sum;


            // 找出所有半混班的位置，记录下来
            HashSet<int> courseOne = new HashSet<int>();
            HashSet<int> courseTwo = new HashSet<int>();

            foreach (GroupList list in BetterEnergyTable.CompareList)
            {
                foreach (Group @group in list.List)
                {
                    for (int i = 0; i < group.Curriculum.table.Count; i++)
                    {
                        List<CourseCell> t = group.Curriculum.table[i];
                        for (int j = 0; j < t.Count; j++)
                        {
                            CourseCell cell = t[j];
                            if (cell.Class != null && cell.Class.Contains("_")
                                && cell.Class.Contains(courseName1) && cell.Class.Contains(courseName2))
                            {
                                if (cell.CourseName == courseName1.Substring(0,2))
                                {
                                    courseOne.Add(i * CourseNumADay + j);
                                }
                                else
                                {
                                    courseTwo.Add(i * CourseNumADay + j);
                                }
                            }
                        }
                    }
                }
            }

            Dictionary<int, int> courseDictionary1 = courseOne.ToDictionary(i => i, i => 0);
            Dictionary<int, int> courseDictionary2 = courseTwo.ToDictionary(i => i, i => 0);

            // 记录下对应位置对应科目同时上课的数量
            foreach (int i in courseOne)
                courseDictionary1[i] = BetterEnergyTable.GetSpecificPositionCourseAmount(i, courseName1.Substring(0, 2));
            foreach (int i in courseTwo)
                courseDictionary2[i] = BetterEnergyTable.GetSpecificPositionCourseAmount(i, courseName2.Substring(0, 2));

            // 对字典进行排序
            var sort =
                from pair in courseDictionary1
                orderby pair.Value descending
                select pair;

            courseDictionary1 = sort.ToDictionary(e => e.Key, e => e.Value);

            sort =
                from pair in courseDictionary2
                orderby pair.Value descending
                select pair;

            courseDictionary2 = sort.ToDictionary(e => e.Key, e => e.Value);

            // 按照数量少的进行交换
            // 交换完成后计算能量值
            int count = courseOne.Count < courseTwo.Count ? courseOne.Count : courseTwo.Count;
            List<int> courseList1 = courseDictionary1.Keys.ToList();
            List<int> courseList2 = courseDictionary2.Keys.ToList();

            for (int i = 0; i < count; i++)
            {
                ExchangeHalfMixedClass(courseList1[i], courseName1,courseName2);
                ExchangeHalfMixedClass(courseList2[i], courseName2,courseName1);
            }

            EnergyTable exchangeEnergyTable = new EnergyTable(BetterEnergyTable.CompareList);
            exchangeEnergyTable.GetCourse();
            exchangeEnergyTable.CalculateEnergy();
            if (exchangeEnergyTable.sum <= rawSum) BetterEnergyTable = exchangeEnergyTable;
            else Console.WriteLine("不适合，请选择其他方案");

        }

        private void ExchangeHalfMixedClass(int place, string courseName1, string courseName2)
        {
            //将半混班的名称和课程进行修改，不需要进行真正的交换
            foreach (GroupList list in BetterEnergyTable.CompareList)
            {
                foreach (Group @group in list.List)
                {
                    for (int i = 0; i < group.Curriculum.table.Count; i++)
                    {
                        CourseCell cell = group.Curriculum.table[place / CourseNumADay][place % CourseNumADay];
                        if (cell.CourseName == courseName1.Substring(0,2) && cell.Class.Contains("_")
                            && cell.Class.Contains(courseName1) && cell.Class.Contains(courseName2))
                        {
                            string[] courses = cell.Class.Split('_');
                            string course1 = courses[0];
                            string course2 = courses[1];
                            int number = int.Parse(courses[2]);

                            cell.Class = course2 + '_' + course1 + '_' + number;
                            cell.CourseName = course2.Substring(0,2);
                        }
                    }
                }
            }

        }
    }
}